package com.galen.manual.service.impl;

import com.galen.manual.context.UserContext;
import com.galen.manual.context.UserContextHolder;
import com.galen.manual.dto.*;
import com.galen.manual.entity.User;
import com.galen.manual.mapper.UserMapper;
import com.galen.manual.service.SmsCodeService;
import com.galen.manual.service.UserService;
import com.galen.manual.utils.JwtUtil;
import com.galen.manual.vo.UserInfoVO;
import com.galen.manual.vo.UserLoginVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final JwtUtil jwtUtil;
    private final RestTemplate restTemplate = new RestTemplate();
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    private final SmsCodeService smsCodeService;

    @Value("${wechat.miniapp.app-id}")
    private String appId;

    @Value("${wechat.miniapp.secret}")
    private String appSecret;

    @Override
    public String login(UserLoginDTO loginDTO) {
        log.info("用户登录: {}", loginDTO.getNickName());

        // 微信小程序登录逻辑
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +
                "&secret=" + appSecret +
                "&js_code=" + loginDTO.getCode() +
                "&grant_type=authorization_code";

        try {
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            if (response != null && response.containsKey("openid")) {
                String openid = (String) response.get("openid");
                String unionid = (String) response.get("unionid");

                // 查找或创建用户
                User user = userMapper.selectByOpenid(openid);
                if (user == null) {
                    user = createUser(loginDTO, openid, unionid);
                }

                // 设置用户上下文
                setUserContext(user);

                // 生成JWT token
                String token = jwtUtil.generateToken(openid, user.getId(), "user");
                log.info("用户登录成功: {}", user.getNickname());
                return token;
            }
        } catch (Exception e) {
            log.error("微信登录失败", e);
        }
        throw new RuntimeException("登录失败");
    }

    @Override
    public UserLoginVO smsLogin(SmsLoginDTO loginDTO, String loginIp) {
        log.info("短信验证码登录: {}", loginDTO.getPhone());

        // 验证手机号格式
        if (!isValidPhone(loginDTO.getPhone())) {
            throw new RuntimeException("手机号格式不正确");
        }

        // 查询用户
        User user = userMapper.selectUserWithAdminInfoByPhone(loginDTO.getPhone());
        if (user == null) {
            // 创建新用户
            user = createSmsUser(loginDTO.getPhone());
        }

        // 验证短信验证码
        if (!smsCodeService.validateSmsCode(loginDTO.getPhone(), loginDTO.getSmsCode(), "login")) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 检查用户状态
        if (user.getStatus() != 1) {
            throw new RuntimeException("账号已被禁用");
        }

        // 标记验证码为已使用
        smsCodeService.markSmsCodeAsUsed(loginDTO.getPhone(), loginDTO.getSmsCode(), "login");

        // 设置用户上下文
        setUserContext(user);

        // 生成JWT token
        String token = jwtUtil.generateToken(user.getPhone(), user.getId(), "user");

        // 构建返回结果
        UserLoginVO loginVO = getUserLoginVO(token, user);

        log.info("短信登录成功: {}", user.getPhone());
        return loginVO;
    }

    @Override
    public void sendSmsCode(SendSmsDTO sendSmsDTO, String ipAddress) {
        log.info("发送短信验证码请求: {}", sendSmsDTO.getPhone());

        // 验证手机号格式
        if (!isValidPhone(sendSmsDTO.getPhone())) {
            throw new RuntimeException("手机号格式不正确");
        }

        // 查询用户，如果不存在则创建
        User user = userMapper.selectByPhone(sendSmsDTO.getPhone());
        if (user == null) {
            // 创建新用户
            user = createSmsUser(sendSmsDTO.getPhone());
            log.info("为新手机号创建用户: {}", sendSmsDTO.getPhone());
        }

        // 使用短信验证码服务发送验证码
        String result = smsCodeService.sendSmsCode(sendSmsDTO, ipAddress);
        log.info("短信验证码发送结果: phone={}, result={}", sendSmsDTO.getPhone(), result);
    }

    @Override
    public UserLoginVO adminLogin(AdminLoginDTO loginDTO, String loginIp) {
        log.info("管理员登录: {}", loginDTO.getUsername());

        // 查询用户及其管理员信息
        User user = userMapper.selectByUsername(loginDTO.getUsername());
        if (user == null) {
            throw new RuntimeException("管理员不存在");
        }
        //密文验证
        String encodePwd = passwordEncoder.encode(loginDTO.getPassword());
        // 验证密码
        if (!passwordEncoder.matches(encodePwd, user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 查询管理员信息
        User userWithAdmin = userMapper.selectUserWithAdminInfo(user.getId());
        if (userWithAdmin == null || userWithAdmin.getIsAdmin() == null || !userWithAdmin.getIsAdmin()) {
            throw new RuntimeException("该账号不是管理员");
        }

        // 检查用户状态
        if (userWithAdmin.getStatus() != 1) {
            throw new RuntimeException("管理员账号已被禁用");
        }

        // 使用包含管理员信息的用户对象
        user = userWithAdmin;

        // 设置用户上下文
        setUserContext(user);

        // 生成JWT token
        String token = jwtUtil.generateToken(user.getUsername(), user.getId(), "admin");

        // 构建返回结果
        UserLoginVO loginVO = getUserLoginVO(token, user);

        log.info("管理员登录成功: {}", user.getUsername());
        return loginVO;
    }

    private static UserLoginVO getUserLoginVO(String token, User user) {
        UserLoginVO loginVO = new UserLoginVO();
        loginVO.setToken(token);
        loginVO.setUserId(user.getId());
        loginVO.setUsername(user.getUsername());
        loginVO.setNickname(user.getNickname());
        loginVO.setPhone(user.getPhone());
        loginVO.setAvatarUrl(user.getAvatarUrl());
        loginVO.setUserLevel(user.getUserLevel());
        loginVO.setStatus(user.getStatus());
        loginVO.setIsAdmin(user.getIsAdmin());
        loginVO.setAdminRole(user.getAdminRole());
        return loginVO;
    }

    @Override
    public UserInfoVO getUserProfile() {
        Long userId = UserContextHolder.getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }

        User user = userMapper.selectUserWithAdminInfo(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfoVO);
        userInfoVO.setIsAdmin(user.getIsAdmin());

        return userInfoVO;
    }

    @Override
    public void updateUserProfile(UserProfileDTO profileDTO) {
        Long userId = UserContextHolder.getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }

        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 更新用户信息
        if (StringUtils.hasText(profileDTO.getNickName())) {
            user.setNickname(profileDTO.getNickName());
        }
        if (StringUtils.hasText(profileDTO.getRealName())) {
            user.setRealName(profileDTO.getRealName());
        }
        if (StringUtils.hasText(profileDTO.getPhone())) {
            user.setPhone(profileDTO.getPhone());
        }
        if (StringUtils.hasText(profileDTO.getAddress())) {
            user.setAddress(profileDTO.getAddress());
        }
        if (StringUtils.hasText(profileDTO.getAvatarUrl())) {
            user.setAvatarUrl(profileDTO.getAvatarUrl());
        }

        userMapper.updateById(user);
        log.info("用户信息更新成功: {}", user.getId());
    }

    // 私有方法
    private User createUser(UserLoginDTO loginDTO, String openid, String unionid) {
        User user = new User();
        user.setOpenid(openid);
        user.setUnionid(unionid);
        user.setNickname(loginDTO.getNickName());
        user.setAvatarUrl(loginDTO.getAvatarUrl());
        user.setUserLevel(1);
        user.setStatus(1);
        user.setTotalCompleted(0);
        user.setTotalEarnings(0.0);
        user.setBalance(0.0);

        userMapper.insert(user);
        log.info("新用户创建成功: {}", user.getId());
        return user;
    }

    private User createSmsUser(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setUsername(phone); // 默认用户名为手机号
        user.setNickname("用户" + phone.substring(7)); // 默认昵称
        user.setUserLevel(1);
        user.setStatus(1);
        user.setTotalCompleted(0);
        user.setTotalEarnings(0.0);
        user.setBalance(0.0);

        userMapper.insert(user);
        log.info("新短信用户创建成功: {}", user.getId());
        return user;
    }

    private void setUserContext(User user) {
        UserContext context = UserContext.of(
                user.getId(),
                user.getUsername(),
                user.getNickname(),
                user.getPhone(),
                user.getAvatarUrl(),
                user.getUserLevel(),
                user.getIsAdmin(),
                user.getAdminRole(),
                user.getStatus()
        );
        UserContextHolder.setUserContext(context);
    }

    private boolean isValidPhone(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }

    private boolean validateSmsCode(User user, String smsCode) {
        if (!StringUtils.hasText(user.getSmsCode()) || user.getSmsCodeExpireTime() == null) {
            return false;
        }

        // 检查验证码是否过期
        if (LocalDateTime.now().isAfter(user.getSmsCodeExpireTime())) {
            return false;
        }

        // 检查验证码是否正确
        return smsCode.equals(user.getSmsCode());
    }

    private void clearSmsCode(User user) {
        user.setSmsCode(null);
        user.setSmsCodeExpireTime(null);
        userMapper.updateById(user);
    }

    // 以下方法暂时保持原有实现，稍后可以移除或重构
    @Override
    public com.galen.manual.vo.UserStatsVO getUserStats() {
        return null;
    }

    @Override
    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.galen.manual.vo.UserManagementVO> getUserManagementPage(com.galen.manual.dto.UserQueryDTO queryDTO) {
        return null;
    }

    @Override
    public com.galen.manual.vo.UserManagementVO getUserManagementDetail(Long id) {
        return null;
    }

    @Override
    public void updateUserLevel(Long id, Integer level) {
    }

    @Override
    public void updateUserStatus(Long id, Integer status) {
    }
}